﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Decode55
{
    public class SAXUnionFiled55Utils
    {
        /**
        * 银联55域
        * 
        * 本域将根据不同的交易种类包含不同的子域。银联处理中心仅在受理方和发卡方之间传递这些适用于IC卡交易的特有数据，而不对它们进行任何修改和处理。
        * 为适应该子域需要不断变化的情况
        * ，本域采用TLV（tag-length-value）的表示方式，即每个子域由tag标签(T)，子域取值的长度(L)和子域取值(V)构成。
        * tag标签的属性为bit
        * ，由16进制表示，占1～2个字节长度。例如，"9F33"为一个占用两个字节的tag标签。而"95"为一个占用一个字节的tag标签
        * 。若tag标签的第一个字节
        * （注：字节排序方向为从左往右数，第一个字节即为最左边的字节。bit排序规则同理。）的后五个bit为"11111"，则说明该tag占两个字节
        * ，例如"9F33"；否则占一个字节，例如"95"。 子域长度（即L本身）的属性也为bit，占1～3个字节长度。具体编码规则如下： a)
        * 当L字段最左边字节的最左bit位（即bit8）为0，表示该L字段占一个字节，它的后续7个bit位（即bit7～bit1）表示子域取值的长度，
        * 采用二进制数表示子域取值长度的十进制数
        * 。例如，某个域取值占3个字节，那么其子域取值长度表示为"00000011"。所以，若子域取值的长度在1～127
        * 字节之间，那么该L字段本身仅占一个字节。 b)
        * 当L字段最左边字节的最左bit位（即bit8）为1，表示该L字段不止占一个字节，那么它到底占几个字节由该最左字节的后续7个bit位
        * （即bit7～bit1）的十进制取值表示。例如，若最左字节为10000010，表示L字段除该字节外，后面还有两个字节。其后续字节
        * 的十进制取值表示子域取值的长度。例如，若L字段为"1000 0001 1111 1111"，表示该子域取值占255个字节。
        * 所以，若子域取值的长度在128～255字节之间，那么该L字段本身需占两个字节
        * 
        * @return tlv list
        */
        public static List<TLV> saxUnionField55_2List(string hexfiled55)
        {
            if (null == hexfiled55)
            {
                throw new Exception("55域的值不能为空!");
            }
            return builderTLV(hexfiled55);
        }
        private static List<TLV> builderTLV(string hexstring)
        {
            List<TLV> tlvs = new List<TLV>();

            int position = 0;
            while (position != hexstring.Length)
            {
                string _hexTag = getUnionTag(hexstring, position);
                position += _hexTag.Length;

                LPositon l_position = getUnionLAndPosition(hexstring, position);
                int _vl = l_position.get_vL();

                position = l_position.get_position();

                string _value = hexstring.Substring(position, _vl * 2);

                position = position + _value.Length;

                tlvs.Add(new TLV(_hexTag, _vl, _value));
            }
            return tlvs;
        }
        public static Dictionary<string, TLV> builderKeyAndTLV(string hexstring)
        {

            Dictionary<string, TLV> tlvs = new Dictionary<string, TLV>();

            int position = 0;
            while (position != hexstring.Length)
            {
                string _hexTag = getUnionTag(hexstring, position);
                position += _hexTag.Length;
                LPositon l_position = getUnionLAndPosition(hexstring, position);
                int _vl = l_position.get_vL();
                position = l_position.get_position();
                string _value = hexstring.Substring(position, _vl * 2);
                position = position + _value.Length;
                tlvs.Add(_hexTag, new TLV(_hexTag, _vl, _value));
            }
            return tlvs;
        }
        /**
	     * 返回最后的Value的长度
	     * 
	     * @param hexstring
	     * @param position
	     * @return
	     */
        private static LPositon getUnionLAndPosition(string hexstring, int position)
        {

            string firstBytestring = hexstring.Substring(position, 2);
            int i = Convert.ToInt32(firstBytestring, 16);
            string hexLength = "";

            if (((IntExtend.UIntMoveRight(i, 7)) & 1) == 0)
            {
                hexLength = hexstring.Substring(position, 2);
                position = position + 2;

            }
            else
            {
                // 当最左侧的bit位为1的时候，取得后7bit的值，
                int _L_Len = i & 127;
                position = position + 2;
                hexLength = hexstring.Substring(position, _L_Len * 2);
                // position表示第一个字节，后面的表示有多少个字节来表示后面的Value值
                position = position + _L_Len * 2;

            }
            return new LPositon(Convert.ToInt32(hexLength, 16), position);

        }


        private static string getUnionTag(string hexstring, int position)
        {
            string firstByte = hexstring.Substring(position, 2);
            int i = Convert.ToInt32(firstByte, 16);
            if ((i & 0x1f) == 0x1f)
            {
                return hexstring.Substring(position, 4);

            }
            else
            {
                return hexstring.Substring(position, 2);
            }
        }

        public class LPositon
        {
            private int _vL;
            private int _position;

            public LPositon(int _vL, int position)
            {
                this._vL = _vL;
                this._position = position;
            }

            public int get_vL()
            {
                return _vL;
            }

            public void set_vL(int _vL)
            {
                this._vL = _vL;
            }

            public int get_position()
            {
                return _position;
            }

            public void set_position(int _position)
            {
                this._position = _position;
            }

        }

        //public static void main(string[] args)
        //{
        //	List<TLV> list = SAXUnionFiled55Utils
        //			.saxUnionField55_2List("9F260879CC8EC5A09FB9479F2701809F100807010199A0B806019F3704000000009F360201C2950500001800009A031205089C01609F02060000000000005F2A02015682027D009F1A0201569F03060000000000009F3303E0F0F09F34036003029F3501119F1E0832303033313233318405FFFFFFFFFF9F090220069F4104000000019F74064543433030319F631030313032303030308030303030303030");
        //	for (TLV tlv : list)
        //	{
        //		System.out.println(tlv);
        //	}
        //}
        // 测试用 55域信息：9F260875539981406550389F2701809F101307010103A00000010A0100000000009EE5D9A99F3704151220139F3602005D950500080068009A032010159C01009F02060000000000005F2A02015682027C009F1A0201569F03060000000000009F33030040009F34033F00029F3501229F1E083130303232373534

    }
}
